%{
///////////////////////
// Token Type Define //
///////////////////////

/* This is the control flow */
#define TOKEN_NULL 0
#define TOKEN_IF 1
#define TOKEN_ELSE 2
#define TOKEN_BEGIN 3
#define TOKEN_END 4
#define TOKEN_FOR 5
#define TOKEN_WHILE 6
// Undefined token is do ... until
// #define TOKEN_DO 7
// #define TOKEN_UNTIL 8

/* Here is for opt symbol */
#define TOKEN_PLUS 7        //+ -
#define TOKEN_STAR 8        //*
#define TOKEN_EQ 9
#define TOKEN_NUM 10
#define TOKEN_VAR 11
#define TOKEN_LPAREN 12		//(
#define TOKEN_RPAREN 13		//)
#define TOKEN_CHAR_STAR 14
#define TOKEN_MUL 15        // /
#define TOKEN_CHAR 16
#define TOKEN_RETURN 17
#define TOKEN_VOID_TYPE 18

/* I have added and 0:00 Mar 23 */
#define TOKEN_INC 107     // ++ --
#define TOKEN_PE 108      // += -= *= /=
#define TOKEN_IS_EQ 101   // ==
#define TOKEN_MORE 102    // >
#define TOKEN_LESS 103    // <
#define TOKEN_MORE_EQ 104 // >=
#define TOKEN_LESS_EQ 105 // <=
#define TOKEN_SEMI 106    // ;
#define TOKEN_COMMA 107   // ,

#define TOKEN_QUE 110     // ?
#define TOKEN_COL 111     // :

/* This is for TYPE_SYSTEM */
#define TOKEN_BYTE_TYPE 26
#define TOKEN_INT_TYPE 20
#define TOKEN_DOUBLE_TYPE 21
#define TOKEN_FLOAT_TYPE 22
#define TOKEN_CHAR_TYPE 23
#define TOKEN_LSB 24 // '['
#define TOKEN_RSB 25 // ']'
#define TOKEN_UINT_TYPE 27

/* You can difine any other token here */
#define TOKEN_INCLUDE 50
#define TOKEN_SHARP 51 // #
#define TOKEN_BLANK 52 // for blank
#define TOKEN_ENTER 53 // \n
#define TOKEN_REF 54

#include <iostream>
#include <cstring>
#include "lex.yy.h"
#include "stat_analyze.h"
#include "ast.h"
using namespace std;

////////////////////////
// type define        //
////////////////////////
#define TOKEN int

///////////////////////
// func define       //
///////////////////////
#define RECONGNIZE(X) {recognize(X);}
int recognize(TOKEN token);
int scan_main(char* fileinputname, char* fileoutputname);
Stat_Analyze* _analyze;

%}

/* Define some regular exp */
number [0-9]
digital ([a-z])|([A-Z])

%%

if          RECONGNIZE(TOKEN_IF)
else        RECONGNIZE(TOKEN_ELSE)
\{          RECONGNIZE(TOKEN_BEGIN)
\}          RECONGNIZE(TOKEN_END)
for         RECONGNIZE(TOKEN_FOR)
while       RECONGNIZE(TOKEN_WHILE)
include     RECONGNIZE(TOKEN_INCLUDE)
#           RECONGNIZE(TOKEN_SHARP)
return      RECONGNIZE(TOKEN_RETURN)

(\+\+)|(\-\-) RECONGNIZE(TOKEN_INC)
(\+\=)|(\-\=)|(\*\=)|(\/\=) RECONGNIZE(TOKEN_PE)
\?          RECONGNIZE(TOKEN_QUE)
\:          RECONGNIZE(TOKEN_COL)
\n          RECONGNIZE(TOKEN_ENTER)
,           RECONGNIZE(TOKEN_COMMA)

\;          RECONGNIZE(TOKEN_SEMI)
\=\=        RECONGNIZE(TOKEN_IS_EQ)
\<\=        RECONGNIZE(TOKEN_LESS_EQ)
\>\=        RECONGNIZE(TOKEN_MORE_EQ)
\>          RECONGNIZE(TOKEN_MORE)
\<          RECONGNIZE(TOKEN_LESS)
char        RECONGNIZE(TOKEN_CHAR_TYPE)
double      RECONGNIZE(TOKEN_DOUBLE_TYPE)
byte        RECONGNIZE(TOKEN_BYTE_TYPE)
int         RECONGNIZE(TOKEN_INT_TYPE)
void        RECONGNIZE(TOKEN_VOID_TYPE)

("+")|("-") RECONGNIZE(TOKEN_PLUS)
("*")       RECONGNIZE(TOKEN_STAR)
("/")       RECONGNIZE(TOKEN_MUL)
(=)         RECONGNIZE(TOKEN_EQ)
"("         RECONGNIZE(TOKEN_LPAREN)
")"         RECONGNIZE(TOKEN_RPAREN)
\".*\"      RECONGNIZE(TOKEN_CHAR_STAR)
'.'         RECONGNIZE(TOKEN_CHAR)
(\ |\t)+	RECONGNIZE(TOKEN_BLANK)

"["         RECONGNIZE(TOKEN_LSB)
"]"         RECONGNIZE(TOKEN_RSB)
	
{number}+     RECONGNIZE(TOKEN_NUM)
{digital}(_|{number}|{digital})* RECONGNIZE(TOKEN_VAR)

%%

int main(int argv, char** args) {
    _analyze=new Stat_Analyze();
	if (argv==1) scan_main(0,0);
	if (argv==2) scan_main(args[1],0);
	if (argv==3) scan_main(args[1],args[2]);
	return 0;
}

int scan_main(char* fileinputname, char* fileoutputname) {
	if (fileinputname==0) 
		yyin=stdin;
	else
		yyin=fopen(fileinputname,"r");
		
	if (fileoutputname==0) 
		yyout=stdout;
	else
		yyout=fopen(fileoutputname,"w");
		
	yylex();
	FILE* fp=fopen("output.txt","w");
	AST::getInstance()->output(fp);
   return 0;
}


int recognize(TOKEN token) {
	if (token==TOKEN_BLANK || token==TOKEN_ENTER) 
		return 1;
	int res=_analyze->gettoken(token, yytext);
	if (!res) {
		printf("Syntax Error");
	}
    //printf("%d ",token);
    return 1;
}
